package com.ztjava.plugin.event;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.jfinal.log.Log;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.ztjava.core.Jsub;
import com.ztjava.plugin.event.core.ApplicationListener;
import com.ztjava.plugin.event.core.Listener;
import com.ztjava.plugin.event.utils.ArrayListMultimap;
import com.ztjava.plugin.event.utils.BeanUtil;
import com.ztjava.plugin.event.utils.ClassUtil;

@SuppressWarnings({"rawtypes", "unchecked"})
public class EventPlugin implements IPlugin{
	private static Log log = Log.getLog(ClassUtil.class);
	// 线程池
	private static ExecutorService pool = null;
	private String cacheName = "EVENT";
	// 重复key的map，使用监听的type，取出所有的监听器
	private static ArrayListMultimap<EventType, ListenerHelper> map = null;
	// 默认不扫描jar包
	private boolean scanJar = false;
	// 默认扫描所有的包
	private String scanPackage = "";
	private RmiServerConfig rmiServerConfig;

	
	/**
	 * 构造EventPlugin
	 * @param scanJar 是否扫描jar
	 * @param scanPackage 扫描的包名
	 */
	public EventPlugin(boolean scanJar, String scanPackage,String cacheName) {
		this.scanJar = scanJar;
		this.scanPackage = scanPackage;
		this.cacheName = cacheName;
	}
	/**
	 * 异步，默认SingleThreadExecutor
	 * @return EventPlugin
	 */
	public EventPlugin async() {
		if (pool == null) {
			pool = Executors.newSingleThreadExecutor(new EventThreadFactory());
		}
		return this;
	}
	public EventPlugin setRmiServer(String host,String serverName) {
		this.rmiServerConfig = new RmiServerConfig(host,serverName);
		return this;
	}
	
	@Override
	public boolean start() {
		if (rmiServerConfig != null) {
			rmiServerConfig.start();
		}
		create();
		EventKit.init(map, pool,cacheName);
		return true;
	}

	@Override
	public boolean stop() {
		// TODO Auto-generated method stub
		return true;
	}
	
	/**
	 * 构造
	 */
	private void create() {
		if (null != map) {
			return;
		}
		// 扫描注解 {@code Listener}
		Set<Class<?>> clazzSet = ClassUtil.scanPackageByAnnotation(scanPackage, scanJar, Listener.class);
		if (clazzSet.isEmpty()) {
			log.warn("Listener is empty! Please check @Listener!");
		}

		List<Class<? extends ApplicationListener>> allListeners = new ArrayList<Class<? extends ApplicationListener>>();
		// 装载所有 {@code ApplicationListener} 的子类
		Class superClass;
		for (Class<?> clazz : clazzSet) {
			superClass = ApplicationListener.class;
			if (superClass.isAssignableFrom(clazz) && !superClass.equals(clazz)) {
				allListeners.add((Class<? extends ApplicationListener>) clazz);
				
			}
		}
		if(rmiServerConfig!=null){
			Cache cache = Redis.use();
			String eventName;
			String tag;
			if(Jsub.single_app){
				cache.del(cacheName);
				System.out.println(cacheName+"已清空");
			}
			for(Class<?> clazz:allListeners){
				eventName = getEventName(clazz);
				tag = clazz.getAnnotation(Listener.class).tag();
				Map<String,Map<String,String>> eventMap;
				if(cache.hexists(cacheName, eventName)){
					eventMap = cache.hget(cacheName, eventName);
				}else {
					eventMap = new HashMap<>();
				}
				String rmi = "rmi://"+rmiServerConfig.getHost()+":"+rmiServerConfig.getPort()+"/"+rmiServerConfig.getName();
				System.out.println(tag+"："+rmi);
				if(eventMap.containsKey(tag)){
					eventMap.get(tag).put(rmi, rmiServerConfig.getName());
				}else {
					Map<String,String> tagMap = new HashMap<String, String>();
					tagMap.put(rmi, rmiServerConfig.getName());
					eventMap.put(tag, tagMap);
				}
				cache.hset(cacheName,eventName, eventMap);
			}
		}
		if (allListeners.isEmpty()) {
			log.warn("Listener is empty! Please check ApplicationListener.class");
		}

		// 监听器排序
		sortListeners(allListeners);

		// 重复key的map，使用监听的type，取出所有的监听器
		map = new ArrayListMultimap<EventType, ListenerHelper>();

		Type type;
		ApplicationListener listener;
		for (Class<? extends ApplicationListener> clazz : allListeners) {
			// 获取监听器上的泛型信息
			type = ((ParameterizedType) clazz.getGenericInterfaces()[0]).getActualTypeArguments()[0];
			// 实例化监听器
			listener = BeanUtil.newInstance(clazz);

			// 监听器上的注解
			Listener annotation = clazz.getAnnotation(Listener.class);
			boolean enableAsync = annotation.enableAsync();
			String tag = annotation.tag();
			
			EventType eventType = new EventType(tag, type);
			map.put(eventType, new ListenerHelper(listener, enableAsync,annotation.response()));
			if (log.isDebugEnabled()) {
				log.debug(clazz + " init~");
			}
		}
	}
	
	private String getEventName(Class listener){

		Type[] a  =((ParameterizedType)(listener.getGenericInterfaces()[0])).getActualTypeArguments();
		String eventName = "";
		for(Type t:a){
			eventName = t.toString();
			eventName = eventName.substring(eventName.lastIndexOf(" ")+1,eventName.length());
		}
		return eventName;
	}
	
	/**
	 * 对所有的监听器进行排序
	 */
	private void sortListeners(List<Class<? extends ApplicationListener>> listeners) {
		Collections.sort(listeners, new Comparator<Class<? extends ApplicationListener>>() {

			public int compare(Class<? extends ApplicationListener> o1,
					Class<? extends ApplicationListener> o2) {

				int x = o1.getAnnotation(Listener.class).order();
				int y = o2.getAnnotation(Listener.class).order();
				return (x < y) ? -1 : ((x == y) ? 0 : 1);
			}
		});
	}
}
